home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / ohlutil / head.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-24  |  8.7 KB  |  384 lines

  1. /* head -- output first part of file(s)
  2.    Copyright (C) 1989, 1990 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /*
  19.  * MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
  20.  *
  21.  * To this port, the same copying conditions apply as to the
  22.  * original release.
  23.  *
  24.  * IMPORTANT:
  25.  * This file is not identical to the original GNU release!
  26.  * You should have received this code as patch to the official
  27.  * GNU release.
  28.  *
  29.  * MORE IMPORTANT:
  30.  * This port comes with ABSOLUTELY NO WARRANTY.
  31.  *
  32.  * $Header: e:/gnu/fileutil/RCS/head.c'v 1.3.0.2 90/06/29 00:46:50 tho Stable $
  33.  */
  34.  
  35. /* Usage: head [-n #] [-lbcqv] [+number #] [+lines] [+blocks] [+chars]
  36.           [+quiet] [+silent] [+verbose] [file...]
  37.  
  38.           head [-#lbcqv] [file...]
  39.  
  40.    Options:
  41.    -n, +number #    Print first # items (default 10).
  42.    -l, +lines        Head by lines (the default).
  43.    -b, +blocks        Head by 512-byte blocks.
  44.    -c, +chars        Head by characters.
  45.    -q, +quiet, +silent    Never print filename headers.
  46.    -v, +verbose        Always print filename headers.
  47.  
  48.    Reads from standard input if no files are given or when a filename of
  49.    ``-'' is encountered.
  50.    By default, filename headers are printed only if more than one file
  51.    is given.
  52.  
  53.    David MacKenzie <djm@ai.mit.edu> */
  54.  
  55. #include <stdio.h>
  56. #include <ctype.h>
  57. #include <sys/types.h>
  58. #include "getopt.h"
  59. #include "system.h"
  60.  
  61. #ifdef STDC_HEADERS
  62. #include <errno.h>
  63. #include <stdlib.h>
  64. #define ISDIGIT(c) (isdigit ((unsigned char) (c)))
  65. #else
  66. #define ISDIGIT(c) (isascii (c) && isdigit (c))
  67.  
  68. extern int errno;
  69. #endif
  70.  
  71. /* Number of lines/chars/blocks to head. */
  72. #define DEFAULT_NUMBER 10
  73.  
  74. #define BLOCKSIZE 512
  75.  
  76. /* Size of atomic reads. */
  77. #define BUFSIZE (BLOCKSIZE*8)
  78.  
  79. /* Masks for the operation mode.  If neither CHARS nor BLOCKS is set,
  80.    head operates by lines. */
  81. #define CHARS 1            /* Head in chars. */
  82. #define BLOCKS 2        /* Head in blocks. */
  83. #define HEADERS 4        /* Write filename headers. */
  84.  
  85. /* When to print the filename banners. */
  86. enum header_mode
  87. {
  88.   multiple_files, always, never
  89. };
  90.  
  91. #ifdef MSDOS
  92.  
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #include <stdarg.h>
  96. #include <io.h>
  97.  
  98. extern  void main (int, char **);
  99. extern  int head_file (char *, int, long);
  100. extern  void write_header (char *);
  101. extern  int head (char *, int, int, long);
  102. extern  int head_chars (char *, int, long);
  103. extern  int head_lines (char *, int, long);
  104. extern  void xwrite (int, char *, int);
  105. extern  long atou (char *);
  106. extern  char *basename (char *);
  107. extern  void error (int status, int errnum, char *message, ...);
  108. extern  void usage (void);
  109.  
  110. #else
  111.  
  112. int head ();
  113. int head_chars ();
  114. int head_file ();
  115. int head_lines ();
  116. long atou ();
  117. void error ();
  118. void usage ();
  119. void write_header ();
  120. void xwrite ();
  121.  
  122. #endif /* __STDC__ */
  123.  
  124. /* The name this program was run with. */
  125. char *program_name;
  126.  
  127. struct option long_options[] =
  128. {
  129.   {"number", 1, NULL, 'n'},
  130.   {"lines", 0, NULL, 'l'},
  131.   {"blocks", 0, NULL, 'b'},
  132.   {"chars", 0, NULL, 'c'},
  133.   {"quiet", 0, NULL, 'q'},
  134.   {"silent", 0, NULL, 'q'},
  135.   {"verbose", 0, NULL, 'v'},
  136.   {NULL, 0, NULL, 0}
  137. };
  138.  
  139. void
  140. main (argc, argv)
  141.      int argc;
  142.      char **argv;
  143. {
  144.   enum header_mode header_mode = multiple_files;
  145.   int errors = 0;        /* Exit status. */
  146.   int mode = 0;            /* Flags. */
  147.   long number = -1;        /* Number of items to print (-1 if undef.). */
  148.   int c;            /* Option character. */
  149.   int longind;            /* Index in `long_options' of option found. */
  150.  
  151.   program_name = argv[0];
  152. #ifdef MSDOS
  153.   strlwr (program_name);
  154. #endif /* not MSDOS */
  155.  
  156.   if (argc > 1 && argv[1][0] == '-' && ISDIGIT (argv[1][1]))
  157.     {
  158.       /* Old option syntax; a dash, one or more digits, and one or
  159.      more option letters.  Move past the number. */
  160.       for (number = 0, ++argv[1]; ISDIGIT (*argv[1]); ++argv[1])
  161.     number = number * 10 + *argv[1] - '0';
  162.       /* Parse any appended option letters with getopt. */
  163.       if (*argv[1])
  164.     *--argv[1] = '-';
  165.       else
  166.     argv[1] = "-l";
  167.     }
  168.   while ((c = getopt_long (argc, argv, "n:lbcqv", long_options, &longind))
  169.      != EOF)
  170.     {
  171.       if (c == 0)
  172.     c = long_options[longind].val;
  173.       switch (c)
  174.     {
  175.     case 'n':
  176.       number = atou (optarg);
  177.       if (number == -1)
  178.         error (1, 0, "invalid number `%s'", optarg);
  179.       break;
  180.     case 'l':
  181.       mode &= ~(CHARS | BLOCKS);
  182.       break;
  183.     case 'b':
  184.       mode |= BLOCKS;
  185.       mode &= ~CHARS;
  186.       break;
  187.     case 'c':
  188.       mode |= CHARS;
  189.       mode &= ~BLOCKS;
  190.       break;
  191.     case 'q':
  192.       header_mode = never;
  193.       break;
  194.     case 'v':
  195.       header_mode = always;
  196.       break;
  197.     default:
  198.       usage ();
  199.     }
  200.     }
  201.  
  202.   if (number == -1)
  203.     number = DEFAULT_NUMBER;
  204.  
  205.   if (mode & BLOCKS)
  206.     number *= BLOCKSIZE;
  207.  
  208.   if (header_mode == always
  209.       || header_mode == multiple_files && optind < argc - 1)
  210.     mode |= HEADERS;
  211.  
  212.   if (optind == argc)
  213.     errors |= head_file ("-", mode, number);
  214.  
  215.   for (; optind < argc; ++optind)
  216.     errors |= head_file (argv[optind], mode, number);
  217.  
  218.   exit (errors);
  219. }
  220.  
  221. int
  222. head_file (filename, mode, number)
  223.      char *filename;
  224.      int mode;
  225.      long number;
  226. {
  227.   int fd;
  228.  
  229. #ifdef MSDOS
  230.   strlwr (filename);
  231. #endif /* MSDOS */
  232.  
  233.   if (!strcmp (filename, "-"))
  234.     {
  235.       filename = "standard input";
  236.       if (mode & HEADERS)
  237.     write_header (filename);
  238.       return head (filename, 0, mode, number);
  239.     }
  240.   else
  241.     {
  242.       fd = open (filename, O_RDONLY);
  243.       if (fd == -1)
  244.     {
  245.       error (0, errno, "%s", filename);
  246.       return 1;
  247.     }
  248.       else
  249.     {
  250.       int errors;
  251.  
  252.       if (mode & HEADERS)
  253.         write_header (filename);
  254.       errors = head (filename, fd, mode, number);
  255.       close (fd);
  256.       return errors;
  257.     }
  258.     }
  259. }
  260.  
  261. void
  262. write_header (filename)
  263.      char *filename;
  264. {
  265.   static int first_file = 1;
  266.  
  267.   if (first_file)
  268.     {
  269.       xwrite (1, "==> ", 4);
  270.       first_file = 0;
  271.     }
  272.   else
  273.     xwrite (1, "\n==> ", 5);
  274.   xwrite (1, filename, strlen (filename));
  275.   xwrite (1, " <==\n", 5);
  276. }
  277.  
  278. int
  279. head (filename, fd, mode, number)
  280.      char *filename;
  281.      int fd;
  282.      int mode;
  283.      long number;
  284. {
  285.   if (mode & (CHARS | BLOCKS))
  286.     return head_chars (filename, fd, number);
  287.   else
  288.     return head_lines (filename, fd, number);
  289. }
  290.  
  291. int
  292. head_chars (filename, fd, chars_to_write)
  293.      char *filename;
  294.      int fd;
  295.      long chars_to_write;
  296. {
  297.   char buffer[BUFSIZE];
  298.   int chars_read;
  299.  
  300.   while (chars_to_write)
  301.     {
  302.       chars_read = read (fd, buffer, BUFSIZE);
  303.       if (chars_read == -1)
  304.     {
  305.       error (0, errno, "%s", filename);
  306.       return 1;
  307.     }
  308.       if (chars_read == 0)
  309.     break;
  310.       if ((long) chars_read > chars_to_write)
  311.     chars_read = (int) chars_to_write;
  312.       xwrite (1, buffer, chars_read);
  313.       chars_to_write -= (long) chars_read;
  314.     }
  315.   return 0;
  316. }
  317.  
  318. int
  319. head_lines (filename, fd, lines_to_write)
  320.      char *filename;
  321.      int fd;
  322.      long lines_to_write;
  323. {
  324.   char buffer[BUFSIZE];
  325.   int chars_read;
  326.   int chars_to_write;
  327.  
  328.   while (lines_to_write)
  329.     {
  330.       chars_read = read (fd, buffer, BUFSIZE);
  331.       if (chars_read == -1)
  332.     {
  333.       error (0, errno, "%s", filename);
  334.       return 1;
  335.     }
  336.       if (chars_read == 0)
  337.     break;
  338.       chars_to_write = 0;
  339.       while (chars_to_write < chars_read)
  340.     if (buffer[chars_to_write++] == '\n' && --lines_to_write == 0)
  341.       break;
  342.       xwrite (1, buffer, chars_to_write);
  343.     }
  344.   return 0;
  345. }
  346.  
  347. /* Write plus error check. */
  348.  
  349. void
  350. xwrite (fd, buffer, count)
  351.      int fd;
  352.      int count;
  353.      char *buffer;
  354. {
  355.   fd = write (fd, buffer, count);
  356.   if (fd != count)
  357.     error (1, errno, "write error");
  358. }
  359.  
  360. /* Convert `str', a string of ASCII digits, into an unsigned integer.
  361.    Return -1 if `str' does not represent a valid unsigned integer. */
  362.  
  363. long
  364. atou (str)
  365.      char *str;
  366. {
  367.   long value;
  368.  
  369.   for (value = 0; ISDIGIT (*str); ++str)
  370.     value = value * 10 + *str - '0';
  371.   return *str ? -1L : value;
  372. }
  373.  
  374. void
  375. usage ()
  376. {
  377.   fprintf (stderr, "\
  378. Usage: %s [-n #] [-lbcqv] [+number #] [+lines] [+blocks] [+chars]\n\
  379.        [+quiet] [+silent] [+verbose] [file...]\n\
  380. \n\
  381.        %s [-#lbcqv] [file...]\n", program_name, program_name);
  382.   exit (1);
  383. }
  384.